grammar MiniC;

// 词法规则名总是以大写字母开头

// 语法规则名总是以小写字母开头

// 每个非终结符尽量多包含闭包、正闭包或可选符等的EBNF范式描述

// 若非终结符由多个产生式组成，则建议在每个产生式的尾部追加# 名称来区分，详细可查看非终结符statement的描述

// 语法规则描述：EBNF范式

// 源文件编译单元定义
compileUnit: ((funcDef | varDecl | constDecl | defineDecl))* EOF;

// 修改：函数定义支持 void、float 以及形参列表
funcDef: (T_INT | T_FLOAT | T_VOID) T_ID T_L_PAREN funcFParams? T_R_PAREN block;

// 新增：函数形参列表，由逗号分隔的单个形参组成
funcFParams: funcFParam (',' funcFParam)*;

// 新增：单个形参规则（支持多维数组参数） 注：这里使用 basicType 替代 bType，bType 同 basicType 修改后：允许第一个方括号里出现可选表达式
funcFParam: basicType T_ID ('[' (expr)? ']' ('[' expr ']')*)?;

// 语句块看用作函数体，这里允许多个语句，并且不含任何语句
block: T_L_BRACE blockItemList? T_R_BRACE;

// 每个ItemList可包含至少一个Item
blockItemList: blockItem+;

// 每个Item可以是一个语句，或者变量声明语句
blockItem: statement | varDecl | constDecl;

// 变量声明支持变量初始化
varDecl: basicType varDef (T_COMMA varDef)* T_SEMICOLON;

// 常量声明
constDecl:
	T_CONST basicType constDef (T_COMMA constDef)* T_SEMICOLON;

// 新增：常量表达式规则
constExp: addExp;

// 新增：专门用于数组初始化的非终结符，支持递归嵌套
arrayInitializer:
	T_L_BRACE (arrayInitializer | expr)? (
		T_COMMA (arrayInitializer | expr)
	)* T_R_BRACE;

// 修改：常量定义支持多维数组声明和嵌套初始化
constDef:
	T_ID (T_L_BRACKET constExp T_R_BRACKET)* T_ASSIGN (
		arrayInitializer
		| expr
	);

// 基本类型
basicType: T_INT | T_FLOAT | T_VOID;

// 修改：变量定义支持多维数组声明和嵌套初始化，以及类型转换变量名
varDef:
	T_ID (T_L_BRACKET constExp T_R_BRACKET)* (
		T_ASSIGN ( arrayInitializer | expr)
	)?
	| '(' basicType '*'* ')' T_ID (
		T_ASSIGN ( arrayInitializer | expr)
	)?;

// 目前语句支持return和赋值语句
statement:
	lVal T_ASSIGN expr T_SEMICOLON									# assignStatement
	| expr? T_SEMICOLON												# expressionStatement
	| block															# blockStatement
	| T_IF T_L_PAREN expr T_R_PAREN statement (T_ELSE statement)?	# ifStatement
	| T_WHILE T_L_PAREN expr T_R_PAREN statement					# whileStatement
	| T_BREAK T_SEMICOLON											# breakStatement
	| T_CONTINUE T_SEMICOLON										# continueStatement
	| T_RETURN expr? T_SEMICOLON									# returnStatement;

// 修改：表达式采用逻辑或最高级
expr: lorExp;

// 逻辑或表达式：优先级最低
lorExp: landExp (T_LOR landExp)*;

// 逻辑与表达式
landExp: eqExp (T_LAND eqExp)*;

// 相等表达式
eqExp: relExp (eqOp relExp)*;

// 相等运算符
eqOp: T_EQ | T_NEQ;

// 关系表达式
relExp: addExp (relOp addExp)*;

// 关系运算符
relOp: T_LT | T_GT | T_LE | T_GE;

// 加减表达式
addExp: mulExp (addOp mulExp)*;

// 加减运算符
addOp: T_ADD | T_SUB;

// 乘除法表达式
mulExp: unaryExp (mulOp unaryExp)*;

// 乘除法运算符
mulOp: T_MUL | T_DIV | T_MOD;

// 修改：扩展一元表达式规则，支持 +, - 和 ! 以及类型转换
unaryExp:
	unaryOp unaryExp
	| '(' basicType '*'* ')' unaryExp // 新增：类型转换支持
	| primaryExp
	| T_ID T_L_PAREN realParamList? T_R_PAREN;

// 新增：一元运算符定义
unaryOp: T_ADD | T_SUB | T_NOT;

// 基本表达式：括号表达式、浮点数、整数、左值表达式
primaryExp:
	T_L_PAREN expr T_R_PAREN
	| T_FLOAT_LITERAL
	| T_HEX_FLOAT_LITERAL // 新增：十六进制浮点数字面量
	| T_HEX_LITERAL // 新增：十六进制字面量
	| T_OCT_LITERAL // 新增：八进制字面量
	| T_DIGIT
	| lVal;

// 实参列表
realParamList: expr (T_COMMA expr)*;

// 修改：左值支持数组下标访问，并支持类型转换
lVal:
	T_ID (T_L_BRACKET expr T_R_BRACKET)*
	| '(' basicType '*'* ')' T_ID (T_L_BRACKET expr T_R_BRACKET)*; // 新增：支持类型转换的左值

// 修改：宏定义声明 - 使用分号结束，而不是换行符
defineDecl: T_DEFINE T_ID expr;

// 用正规式来进行词法规则的描述

T_L_PAREN: '(';
T_R_PAREN: ')';
T_SEMICOLON: ';';
T_L_BRACE: '{';
T_R_BRACE: '}';

T_ASSIGN: '=';
T_COMMA: ',';

T_ADD: '+';
T_SUB: '-';
T_MUL: '*';
T_DIV: '/';
T_MOD: '%';

// 要注意关键字同样也属于T_ID，因此必须放在T_ID的前面，否则会识别成T_ID
T_RETURN: 'return';
T_INT: 'int';
T_VOID: 'void';
T_FLOAT: 'float'; // 新增：支持float关键字
T_CONST: 'const';

T_IF: 'if';
T_ELSE: 'else';

T_WHILE: 'while';
T_BREAK: 'break';
T_CONTINUE: 'continue';

T_LT: '<';
T_GT: '>';
T_LE: '<=';
T_GE: '>=';

T_EQ: '==';
T_NEQ: '!=';

T_LAND: '&&';
T_LOR: '||';

T_L_BRACKET: '[';
T_R_BRACKET: ']';

T_NOT: '!';

// 修改：宏定义关键字
T_DEFINE: '#define';

T_HEX_LITERAL: '0' [xX] [0-9a-fA-F]+; // 新增：十六进制字面量规则
T_OCT_LITERAL:
	'0' [0-7]+; // 新增：八进制字面量规则 (确保在T_DIGIT前，如果T_DIGIT能匹配'0'开头的数字)

T_ID: [a-zA-Z_][a-zA-Z0-9_]*;
T_DIGIT: '0' | [1-9][0-9]*;
T_FLOAT_LITERAL:
	[0-9]+ '.' [0-9]* ([eE][+-]? [0-9]+)?
	| '.' [0-9]+ ([eE][+-]? [0-9]+)?
	| [0-9]+ [eE][+-]? [0-9]+;

// 新增：十六进制浮点数字面量规则
T_HEX_FLOAT_LITERAL:
	'0' [xX] [0-9a-fA-F]+ '.' [0-9a-fA-F]* [pP][+-]? [0-9]+
	| '0' [xX] '.' [0-9a-fA-F]+ [pP][+-]? [0-9]+
	| '0' [xX] [0-9a-fA-F]+ [pP][+-]? [0-9]+;

/* 空白符丢弃 */
WS: [ \r\n\t]+ -> skip;
LINE_COMMENT: '//' ~[\r\n]* -> skip;
BLOCK_COMMENT: '/*' .*? '*/' -> skip;